package com.unitd.base.module.comm.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.unitd.base.module.comm.interceptor.LogInterceptor;
import com.unitd.base.module.consumer.comm.interceptor.AuthorizationInterceptor;
import com.unitd.base.module.consumer.comm.resolver.LoginUserHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * 当前应用的WEB 初始配置类
 * 当前定义的基于springboot的配置器,具体可以参考
 * https://blog.csdn.net/songzehao/article/details/99641594
 *
 * @author hudan
 * @version 1.0
 * @filename ApiConfiguration.java
 * @copyright www.unitd.com
 * @date 2020-07-05
 */
@Configuration
public class ShopConfiguration extends WebMvcConfigurerAdapter {

    /**
     * 生命自定义的权限拦截器
     *
     * @return 权限拦截器
     */
    @Bean
    public AuthorizationInterceptor getMyAuthorizationInterceptor() {
        return new AuthorizationInterceptor();
    }

    /**
     * 添加拦截器处理
     *
     * @param registry 拦截器注册对象
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加登录校验拦截器
        registry.addInterceptor(getMyAuthorizationInterceptor())
                // 拦截项目中的哪些请求
                .addPathPatterns("/api/**");

        // 为了加载拦截器 需要 日志拦截器 （登录拦截和权限拦截已在shiro实现，看实现 情况处理）
        registry.addInterceptor(new LogInterceptor())
                // 拦截项目中的哪些请求
                .addPathPatterns("/**")
                //对项目中的哪些请求不拦截
                .excludePathPatterns("/statics/**")
                .excludePathPatterns("/**/**.html")
                .excludePathPatterns("/**/**.js");
    }

    /**
     * 静态资源路径
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }

    /**
     * 参数解析器
     * 利用HandlerMethodArgumentResolver统一获取当前登录用户信息
     *
     * @param argumentResolvers 参数解析器
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new LoginUserHandlerMethodArgumentResolver());
    }

    /**
     * 或者响应信息转换器
     *
     * @param converters 转换器
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fjc = new FastJsonHttpMessageConverter();
        FastJsonConfig fj = new FastJsonConfig();
        // 消除对同一对象循环引用的问题，默认为false（如果不配置有可能会进入死循环）
        fj.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        // 是否输出值为null的字段,默认为false
        fj.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
        fj.setSerializerFeatures(SerializerFeature.QuoteFieldNames);
        fj.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat);

        // List字段如果为null,输出为[],而非null
        fj.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty);
        // 字符类型字段如果为null,输出为"",而非null
        fj.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty);
        // Boolean字段如果为null,输出为false,而非null
        fj.setSerializerFeatures(SerializerFeature.WriteNullBooleanAsFalse);
        // 是否输出值为null的字段,默认为false
        fj.setSerializerFeatures(SerializerFeature.WriteMapNullValue);

        fjc.setSupportedMediaTypes(getSupportedMediaTypes());
        fjc.setFastJsonConfig(fj);
        converters.add(fjc);
    }

    /**
     * 获取可支持的多媒体类型
     *
     * @return 可支持的多媒体类型
     */
    private List<MediaType> getSupportedMediaTypes() {
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        return supportedMediaTypes;
    }
}